package light.mvc.controller.workflow;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import light.mvc.controller.base.BaseController;
import light.mvc.framework.constant.GlobalConstant;
import light.mvc.model.sys.Tuser;
import light.mvc.model.workflow.TapproveInfo;
import light.mvc.model.workflow.Tfield;
import light.mvc.model.workflow.Tform;
import light.mvc.model.workflow.TformTemplate;
import light.mvc.pageModel.base.Grid;
import light.mvc.pageModel.base.Json;
import light.mvc.pageModel.base.PageFilter;
import light.mvc.pageModel.base.SessionInfo;
import light.mvc.pageModel.sys.User;
import light.mvc.pageModel.workflow.ApproveInfo;
import light.mvc.pageModel.workflow.FieldPageModel;
import light.mvc.pageModel.workflow.FormTemplate;
import light.mvc.pageModel.workflow.MyActivityCoordinates;
import light.mvc.pageModel.workflow.TaskView;
import light.mvc.service.sys.UserServiceI;
import light.mvc.service.workflow.FormServiceI;
import light.mvc.service.workflow.FormTemplateServiceI;
import light.mvc.service.workflow.ProcessDefinitionServiceI;
import light.mvc.utils.LightmvcConstants;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

@Controller
@RequestMapping({ "/apply" })
public class FormFlowController extends BaseController {
	@Autowired
	private FormServiceI formService;
	@Autowired
	private UserServiceI userService;
	@Autowired
	private FormTemplateServiceI formTemplateService;
	@Autowired
	private ProcessDefinitionServiceI processDefinitionService;

	/** 起草申请（表单模板列表） */
	@RequestMapping({ "begin" })
	public String formTemplateList() {
		return "/workflow/formTemplateList";
	}

	@ResponseBody
	@RequestMapping({ "dataGrid" })
	public Grid formTemplateListData() {
		Grid grid = new Grid();
		List<FormTemplate> formTemplateList = formTemplateService.findAll();
		grid.setRows(formTemplateList);
		grid.setTotal(Long.valueOf(grid.getRows().size()));
		return grid;
	}

	/** 提交申请页面 */
	@RequestMapping({ "submitUI" })
	public String submitUI(HttpServletRequest req, @RequestParam("formTemplateId") String formTemplateId) {
		req.setAttribute("formTemplateId", formTemplateId);
		List<Tfield> fields = new ArrayList<Tfield>();
		fields.addAll(formTemplateService.getById(Long.valueOf(formTemplateId)).getFields());
		req.setAttribute("fields", fields);
		return "/workflow/formSubmit";
	}

	/**
	 * 提交申请
	 * 
	 * @throws IOException
	 * @throws IllegalStateException
	 */
	@RequestMapping(value = "submit", method = RequestMethod.POST)
	@ResponseBody
	public Json submit(HttpServletRequest req){

		// 生成一个Form对象，表示本次的申请信息
		Tform tform = new Tform();
		SessionInfo sessionInfo = (SessionInfo) req.getSession().getAttribute(GlobalConstant.SESSION_INFO);

		Tuser applicant = userService.getTuserByLoginName(getUser(req, sessionInfo));
		tform.setApplicant(applicant); // 申请人，当前登录的用户

		tform.setApplyTime(new Date()); // 申请时间，当前时间
		
		List<FieldPageModel> fields = new ArrayList<FieldPageModel>();
		TformTemplate tformTemplate = formTemplateService.getTformTemplateById(Long.valueOf(req.getParameter("formTemplateId").trim()));
		tform.setFormTemplate(tformTemplate);
		for (Tfield tfield : tformTemplate.getFields()) {
			String desc = tfield.getDescription();
			if (LightmvcConstants.APPLICANT_NAME_FIELD.equals(desc)) {
				fields.add(new FieldPageModel(desc, applicant.getName()));
			}else if(LightmvcConstants.STAFF_ENDTIME.equals(desc) || LightmvcConstants.STAFF_STARTTIME.equals(desc)){
				fields.add(new FieldPageModel(desc, req.getParameter(desc)));
				if (LightmvcConstants.STAFF_STARTTIME.equals(desc)) {
					tform.setStartTime(req.getParameter(desc));
				}else if(LightmvcConstants.STAFF_ENDTIME.equals(desc)){
					tform.setEndTime(req.getParameter(desc));
				}
			}else{
				fields.add(new FieldPageModel(desc, req.getParameter(desc)));
			}
		}
		Json json = new Json();
		try {
			String isProxy = req.getParameter(LightmvcConstants.PROXY_NAME_FIELD);
			formService.submit(tform, fields, isProxy, sessionInfo.getLoginName(), sessionInfo.getName());
			// 保存表单，并开始流转
			json.setSuccess(true);
			json.setMsg("提交成功");
		} catch (Exception e) {
			json.setSuccess(false);
			json.setMsg("提交出错");
			e.printStackTrace();
		}
		return json; // 转到我的申请查询
	}

	/**
	 * @param req
	 * @param sessionInfo
	 * @return
	 */
	private User getUser(HttpServletRequest req, SessionInfo sessionInfo) {
		String hasApplicantNameField = (String) req.getParameter(LightmvcConstants.APPLICANT_NAME_FIELD);
		User user = new User();
		if (hasApplicantNameField != null && !hasApplicantNameField.equals("")) {
			user.setLoginName(hasApplicantNameField);
		} else {
			user.setLoginName(sessionInfo.getLoginName());
		}
		return user;
	}

	/**
	 * 保存上传的文件，使用UUID做为文件名，并返回文件存储的全路径
	 * 
	 * @param upload
	 * @return
	 * @throws IOException
	 * @throws IllegalStateException
	 */
	protected String saveUploadFile(HttpServletRequest req, CommonsMultipartFile upload) throws IllegalStateException, IOException {
		String basePath = req.getSession().getServletContext().getRealPath("/WEB-INF/upload_files/"); // 返回结果最后没有'/'
		String subPath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
		// 如果文件夹不存在，就创建
		File dir = new File(basePath + subPath);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		String path = basePath + subPath + UUID.randomUUID().toString(); // 使用UUID做为文件名，以解决重名的问题
		File destFile = new File(path);
		// 移动到目的地，return true if and only if the renaming succeeded; false otherwise
		// 如果目标文件存在就会失败返回false.
		// 如果目标文件所在的文件夹不存在，就会失败返回false.
		upload.transferTo(destFile);

		return path;
	}

	/** 我的申请查询 */
	@RequestMapping({ "applyInfo" })
	public String applyInfo() {
		return "/workflow/applyInfo";
	}

	/** 我的申请查询 */
	@RequestMapping({ "applyInfoData" })
	@ResponseBody
	public Grid applyInfoData(HttpServletRequest req, PageFilter ph) {
		SessionInfo sessionInfo = (SessionInfo) req.getSession().getAttribute(GlobalConstant.SESSION_INFO);
		User user = new User();
		user.setLoginName(sessionInfo.getLoginName());
		Tuser tuser = userService.getTuserByLoginName(user);
		Grid grid = new Grid();
		grid.setRows(formService.getByUser(tuser, ph));
		grid.setTotal(formService.count(tuser));
		return grid;
	}

	/** 待我审批（我的任务列表） */
	@RequestMapping({ "handle" })
	public String taskListUI() {
		return "/workflow/myTaskList";
	}

	@RequestMapping({ "handleData" })
	@ResponseBody
	public Grid taskListData(HttpServletRequest req) {
		Grid grid = new Grid();
		SessionInfo sessionInfo = (SessionInfo) req.getSession().getAttribute(GlobalConstant.SESSION_INFO);
		User user = new User();
		user.setLoginName(sessionInfo.getLoginName());
		List<TaskView> taskViewList = formService.findMyTaskViewList(user);
		grid.setRows(taskViewList);
		grid.setTotal(Long.valueOf(grid.getRows().size()));
		return grid;
	}

	@RequestMapping({ "approveUI" })
	public String approveUI(HttpServletRequest req, @RequestParam("id") String id, @RequestParam("formId") String formId) {
		// 准备数据：当前任务节点中所有流出连线的名称
		Set<String> outcomes = formService.getOutcomesByTaskId(id);
		req.setAttribute("id", id);
		req.setAttribute("formId", formId);
		req.setAttribute("outcomes", outcomes);
		List<Tfield> filTfields = formService.getTfieldsByTaskId(id, formId);
		req.setAttribute("fields", filTfields);
		return "/workflow/myTaskListApprove";
	}

	/** 审批处理 */
	@RequestMapping({ "approve" })
	@ResponseBody
	public Json approve(HttpServletRequest req, ApproveInfo info, @RequestParam(value = "outcome", required = false) String outcome) {
		SessionInfo sessionInfo = (SessionInfo) req.getSession().getAttribute(GlobalConstant.SESSION_INFO);
		User user = new User();
		user.setLoginName(sessionInfo.getLoginName());
		Tuser tuser = userService.getTuserByLoginName(user);
		// 生成一个ApproveInfo对象，表示本次的审批信息
		TapproveInfo approveInfo = new TapproveInfo();

		approveInfo.setApproval(info.isApproval()); // 本次是否同意
		approveInfo.setComment(info.getComment());
		approveInfo.setForm(formService.getById(info.getFormId()));

		approveInfo.setApprover(tuser); // 审批人，当前登录的用户
		approveInfo.setApproveTime(new Date()); // 当前时间

		// 对表单进行审批处理（保存审批信息、完成任务、维护表单状态）
		Json json = new Json();
		try {
			formService.approve(approveInfo, info.getTaskId(), outcome);
			json.setSuccess(true);
			json.setMsg("成功");
		} catch (Exception e) {
			json.setSuccess(false);
			json.setMsg("失败");
			e.printStackTrace();
		}
		return json; // 转到待我审批
	}

	/** 查看流转记录UI */
	@RequestMapping({ "approvedHistoryUI" })
	public String approvedHistoryUI(HttpServletRequest req, @RequestParam("formId") String formId) {
		req.setAttribute("formId", formId);
		return "/workflow/applyInfoCheck";
	}

	/** 查看流转记录 */
	@RequestMapping({ "approvedHistoryUIData" })
	@ResponseBody
	public List<ApproveInfo> approvedHistory(@RequestParam("formId") String formId) {

		List<ApproveInfo> approveInfos = formService.getApproveInfosByFormId(formId);
		return approveInfos;
	}

	/** 查看我的申请图形流转记录 */
	@RequestMapping({ "checkMyApplyInfo" })
	public String checkMyApplyInfo(HttpServletRequest req, @RequestParam("id") String id) {
		Tform tform = formService.getById(Long.valueOf(id));
		String piId = tform.getProcessInstanceId();
		List<MyActivityCoordinates> activityCoordinates = processDefinitionService.getActivityCoordinates(piId);
		req.setAttribute("piId", piId);
		req.setAttribute("activityCoordinates", activityCoordinates);
		return "/workflow/applyInfoPicCheck";
	}

	/**
	 * 查看我的申请图形流转记录数据
	 * @throws IOException
	 */
	@RequestMapping(value = "checkMyApplyInfoData", method = RequestMethod.GET)
	public void checkMyApplyInfoData(HttpServletResponse response, HttpServletRequest req, @RequestParam("piId") String piId) throws IOException {
		// String proccessInstanceId = new String(piId.getBytes("ISO8859-1"), "UTF-8");
		String proccessInstanceId = URLDecoder.decode(piId, "utf-8");
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		String pdId = processDefinitionService.getProcessDefinitionId(proccessInstanceId);
		if (pdId == null) {
			BufferedWriter bw = new BufferedWriter(response.getWriter());
			bw.write("该申请流程已结束！");
			return;
		}
		InputStream inputStream = processDefinitionService.getProcessImageResourceAsStream(pdId);
		bis = new BufferedInputStream(inputStream);
		bos = new BufferedOutputStream(response.getOutputStream());
		byte[] buff = new byte[2048];
		int bytesRead;
		while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
			bos.write(buff, 0, bytesRead);
		}
		bis.close();
		bos.close();
	}

	/**
	 * download查看审批人的申请文件
	 * 
	 * @throws IOException
	 */
	@RequestMapping(value = "downloadApplyFile", method = RequestMethod.GET)
	@ResponseBody
	public void downloadApplyFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("formId") String formId) throws Exception {
		Tform form = formService.getById(Long.valueOf(formId));
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		String newFileName = new String("申请信息文档.doc");
		long fileLength = new File(form.getPath()).length();
		response.setHeader("Content-disposition", "attachment; filename=" + new String(newFileName.getBytes("gb2312"), "ISO8859-1"));
		response.setHeader("Content-Length", String.valueOf(fileLength));
		bis = new BufferedInputStream(new FileInputStream(form.getPath()));
		bos = new BufferedOutputStream(response.getOutputStream());
		byte[] buff = new byte[2048];
		int bytesRead;
		while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
			bos.write(buff, 0, bytesRead);
		}
		bis.close();
		bos.close();

	}
}
